﻿//  Copyright (c) 2011 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;

namespace DNA.OpenAPI.Atom
{
    /// <summary>
    /// Provides the class helps you to build the Atom feed document / object quickly
    /// </summary>
    public class AtomFeedBuilder
    {
        private AtomFeed feed;
        
        public AtomFeedBuilder(AtomFeed atomFeed)
        {
            feed = atomFeed;
            if (feed.Entries == null)
                feed.Entries = new List<AtomEntry>();
        }

        public AtomFeedBuilder(string title, string subTitle = "", string id = "", string copyright = "")
        {
            feed = new AtomFeed()
            {
                Title = title,
                Entries = new List<AtomEntry>()
            };
            if (!string.IsNullOrEmpty(subTitle)) feed.SubTitle = subTitle;
            if (!string.IsNullOrEmpty(id)) feed.ID = id;
            if (!string.IsNullOrEmpty(copyright)) feed.CopyRight = copyright;
        }
        
        public void SetBaseInfo(string title, string subTitle = "", string id = "", string copyright = "")
        {
            feed.Title = title;
            if (!string.IsNullOrEmpty(subTitle)) feed.SubTitle = subTitle;
            if (!string.IsNullOrEmpty(id)) feed.ID = id;
            if (!string.IsNullOrEmpty(copyright)) feed.CopyRight = copyright;
        }

        public void SetLogo(string uri)
        {
            if (!string.IsNullOrEmpty(uri))
                feed.Logo = uri;
        }

        public void SetIcon(string uri)
        {
            if (!string.IsNullOrEmpty(uri))
                feed.Icon = uri;
        }

        public void SetLastUpdated(DateTime date)
        {
            feed.Updated = date;
        }

        public void SetGenerator(string uri, string version = "1.0", string text = "")
        {
            feed.Generator = new AtomGenerator()
               {
                   Text = text,
                   NavigateUrl = uri,
                   Version = version
               };
        }

        public void AddCategories(IEnumerable<AtomCategory> categories)
        {
            if (feed.Categories == null)
                feed.Categories = new List<AtomCategory>();
            feed.Categories.AddRange(categories);
        }

        public AtomCategory AddCategory(string term,string label="", string schema="")
        {
            var cat = new AtomCategory() { Term=term};
            if (!string.IsNullOrEmpty(label)) cat.Text = label;
            if (!string.IsNullOrEmpty(schema)) cat.Scheme = schema;
            this.AddCategory(cat);
            return cat;
        }

        public void AddCategory(AtomCategory category)
        {
            if (feed.Categories == null)
                feed.Categories = new List<AtomCategory>();
            feed.Categories.Add(category);
        }

        public void AddContributors(IEnumerable<AtomPersonConstruct> contributors)
        {
            if (feed.Contributors == null) feed.Contributors = new List<AtomPersonConstruct>();
            feed.Contributors.AddRange(contributors);
        }

        public AtomPersonConstruct AddContributor(string name, string uri = "", string email = "")
        {
            var person = new AtomPersonConstruct() { Name = name };
            if (!string.IsNullOrEmpty(uri)) person.Uri = uri;
            if (!string.IsNullOrEmpty(email)) person.Email = email;
            this.AddContributor(person);
            return person;
        }

        public void AddContributor(AtomPersonConstruct person)
        {
            if (feed.Contributors == null) feed.Contributors = new List<AtomPersonConstruct>();
            feed.Contributors.Add(person);
        }

        public void AddEntries<T>(IEnumerable<T> model, Action<T, AtomEntryBuilder> director)
            where T:class
        {
            foreach (var e in model)
            {
                var builder = new AtomEntryBuilder();
                director(e, builder);
                AddEntry(builder.Entry);
            }
        }

        public void AddEntries(IEnumerable<AtomEntry> entries)
        {
            feed.Entries.AddRange(entries);
        }

        public void AddEntry(AtomEntry entry)
        {
            feed.Entries.Add(entry);
        }

        public string GetXml()
        {
            var ser = new XmlSerializer(typeof(AtomFeed));
            var xml = "<?xml version=\"1.0\">";
            using (var stream = new MemoryStream())
            {
                using (var writer = new XmlTextWriter(stream, System.Text.Encoding.UTF8))
                {
                    writer.Formatting = Formatting.None;
                    ser.Serialize(writer, feed);
                    writer.Flush();
                    stream.Position = 0;
                    var reader = new StreamReader(stream, System.Text.Encoding.UTF8);
                    xml = reader.ReadToEnd();
                    reader.Close();
                }
            }
            return xml;
        }

        public AtomFeed GetAtomFeed()
        {
            return feed;
        }
    }
}
